package middle.ground.db;

import middle.ground.core.annotation.Column;
import middle.ground.core.annotation.Persist;
import middle.ground.core.annotation.Table;
import middle.ground.utils.SingletonObject;
import middle.ground.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author jrl
 * @author jrl
 * @date 2020-12-01
 */
public class BaseDaoImpl<T> implements BaseDao<T> {

	private static Logger logger = LoggerFactory.getLogger(BaseDaoImpl.class);
	private static final String ORACLE_ROWNUM_ALIAS = "oraclerownumrandomcolname";

	@Autowired
	protected JdbcTemplate jdbcTemplate;

	protected ResultSetExtractor<T> defaultEntityResultSetExtractor = new ResultSetExtractor<T>() {
		@Override
		public T extractData(ResultSet rs) throws SQLException, DataAccessException {
			return resolveOne(rs);
		}
	};

	protected ResultSetExtractor<List<T>> defaultListResultSetExtractor = new ResultSetExtractor<List<T>>() {
		@Override
		public List<T> extractData(ResultSet rs) throws SQLException, DataAccessException {
			return resolve(rs);
		}
	};

	/**
	 * 定义一个T的类对象，用于获取泛型的class
	 */
	protected Class<T> entityClass;

	/**
	 * 通过反射获取T实际的Class对象
	 *
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected Class<T> getEntityClass() {
		if (null == entityClass) {
			entityClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		}

		return entityClass;
	}

	@Override
	public T add(T t) {
		Table table = getTableAnnotation();
		String idField = table.idField();
		String sequence = table.sequence();
		if (StringUtils.isNotBlank(sequence)) {
			Integer id = jdbcTemplate.queryForObject("SELECT " + sequence + ".NEXTVAL FROM DUAL", Integer.class);
			try {
				entityClass.getDeclaredMethod(getSetter(idField), Integer.class).invoke(t, id);
			} catch (Exception e) {
				throw new RuntimeException("设置主键失败[" + entityClass.getName() + "#" + idField, e);
			}
		}

		StringBuilder valueSql = new StringBuilder();
		StringBuilder sql = new StringBuilder("INSERT INTO ");
		sql.append(table.table());
		sql.append(" (");

		Field[] fields = entityClass.getDeclaredFields();
		final List<Object> values = new ArrayList<Object>();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			String fieldName = field.getName();
			if ("createTime".equals(fieldName) || Modifier.isStatic(field.getModifiers())) {
				continue;
			}

			Persist persist = field.getAnnotation(Persist.class);
			if (null != persist) {
				String[] persistValues = persist.value();
				boolean uninsertable = false;
				for (int j = 0; j < persistValues.length; j++) {
					if (Persist.UNINSERTABLE.equals(persistValues[j])) {
						uninsertable = true;
						break;
					}
				}
				if (uninsertable) {
					continue;
				}
			}

			String temp = null;
			Column column = field.getAnnotation(Column.class);
			if (null != column && StringUtil.isNotBlank(column.value())) {
				temp = column.value();
			} else {
				temp = translateField2Column(fieldName);
			}

			try {
				Object value = entityClass.getDeclaredMethod(getGetter(fieldName)).invoke(t);
				if (column != null && value != null && column.isJson()) {
					value = SingletonObject.OBJECT_MAPPER.writeValueAsString(value);
				}
				if (null != value) {
					values.add(value);
					sql.append(temp).append(",");
					valueSql.append("?,");
				}
			} catch (Exception e) {
				logger.error("调用[" + entityClass.getName() + "#" + fieldName + "]的Getter方法异常");
			}
		}

		int len = sql.length() - 1;
		if (sql.lastIndexOf(StringUtil.COMMA) != len) {
			throw new RuntimeException("没有要插入的数据");
		}

		sql.deleteCharAt(len);
		valueSql.deleteCharAt(valueSql.length() - 1);
		sql.append(") VALUES (").append(valueSql).append(")");

		jdbcTemplate.update(sql.toString(), new PreparedStatementSetter() {
			@Override
			public void setValues(PreparedStatement ps) throws SQLException {
				for (int i = 0; i < values.size(); i++) {
					Object value = values.get(i);
					if (value instanceof java.sql.Date) {
						ps.setDate(i + 1, (java.sql.Date) value);
					} else if (value instanceof Timestamp) {
						ps.setTimestamp(i + 1, (Timestamp) value);
					} else if (value instanceof Date) {
						ps.setTimestamp(i + 1, new Timestamp(((Date) value).getTime()));
					} else {
						ps.setObject(i + 1, value);
					}
				}
			}
		});

		return t;
	}

	@Override
	public void batchAdd(List<T> ts) {
		batchAdd(ts, 2000);
	}

	@Override
	public void batchAdd(List<T> ts, int batchSize) {
		Connection connection = null;
		PreparedStatement statement = null;
		try {
			connection = jdbcTemplate.getDataSource().getConnection();
			connection.setAutoCommit(false);
			statement = connection.prepareStatement(getInsertSql());

			int count = 0;
			for (T t : ts) {
				List<Object> values = getInsertParam(t);
				for (int i = 0; i < values.size(); i++) {
					Object value = values.get(i);
					if (value instanceof java.sql.Date) {
						statement.setDate(i + 1, (java.sql.Date) value);
					} else if (value instanceof Timestamp) {
						statement.setTimestamp(i + 1, (Timestamp) value);
					} else if (value instanceof Date) {
						statement.setTimestamp(i + 1, new Timestamp(((Date) value).getTime()));
					} else {
						statement.setObject(i + 1, value);
					}
				}
				statement.addBatch();

				if (++count % batchSize == 0) {
					statement.executeBatch();
					connection.commit();
				}
			}
			statement.executeBatch();
			connection.commit();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		} finally {
			if (statement != null) {
				try {
					statement.close();
				} catch (SQLException e) {
					logger.error(e.getMessage(), e);
				}
			}
			if (connection != null) {
				try {
					connection.close();
				} catch (SQLException e) {
					logger.error(e.getMessage(), e);
				}
			}
		}
	}

	@Override
	public int update(T t) {
		return update(t, false);
	}

	@Override
	public int updateNotNull(T t) {
		return update(t, true);
	}

	private int update(T t, boolean updateNotNull) {
		Table table = getTableAnnotation();
		String idField = table.idField();

		StringBuilder sql = new StringBuilder("UPDATE ");
		sql.append(table.table());
		sql.append(" SET ");

		Field[] fields = entityClass.getDeclaredFields();
		final List<Object> values = new ArrayList<Object>();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			String fieldName = field.getName();
			if (idField.equals(fieldName) || "createTime".equals(fieldName) || Modifier.isStatic(field.getModifiers())) {
				continue;
			}

			Persist persist = field.getAnnotation(Persist.class);
			if (null != persist) {
				String[] persistValues = persist.value();
				boolean unupdatable = false;
				for (int j = 0; j < persistValues.length; j++) {
					if (Persist.UNUPDATABLE.equals(persistValues[j])) {
						unupdatable = true;
						break;
					}
				}
				if (unupdatable) {
					continue;
				}
			}

			String temp = null;
			Column column = field.getAnnotation(Column.class);
			if (null != column) {
				temp = column.value();
			} else {
				temp = translateField2Column(fieldName);
			}

			try {
				Object value = entityClass.getDeclaredMethod(getGetter(fieldName)).invoke(t);
				if (column != null && value != null && column.isJson()) {
					value = SingletonObject.OBJECT_MAPPER.writeValueAsString(value);
				}
				if (null == value) {
					if (updateNotNull) {
						continue;
					}
				}

				values.add(value);
				sql.append(temp).append("=?,");
			} catch (Exception e) {
				logger.error("调用[" + entityClass.getName() + "#" + fieldName + "]的Getter方法异常：" + e.getMessage());
			}
		}

		int len = sql.length() - 1;
		if (sql.lastIndexOf(StringUtil.COMMA) != len) {
			throw new RuntimeException("没有要更新的数据");
		}
		sql.deleteCharAt(len);

		String temp = table.idColumn();
		if (null == temp) {
			temp = translateField2Column(idField);
		}
		try {
			values.add(entityClass.getDeclaredMethod(getGetter(idField)).invoke(t));
		} catch (Exception e) {
			logger.error("获取ID失败[" + entityClass.getName() + "#" + idField + "]：" + e.getMessage());
		}

		sql.append(" WHERE ").append(temp).append("=?");

		return jdbcTemplate.update(sql.toString(), new PreparedStatementSetter() {
			@Override
			public void setValues(PreparedStatement ps) throws SQLException {
				for (int i = 0; i < values.size(); i++) {
					Object value = values.get(i);
					if (value instanceof java.sql.Date) {
						ps.setDate(i + 1, (java.sql.Date) value);
					} else if (value instanceof Timestamp) {
						ps.setTimestamp(i + 1, (Timestamp) value);
					} else if (value instanceof Date) {
						ps.setTimestamp(i + 1, new Timestamp(((Date) value).getTime()));
					} else {
						ps.setObject(i + 1, value);
					}
				}
			}
		});
	}

	@Override
	public void merge(T t) {
		Table table = getTableAnnotation();
		String idField = table.idField();
		Object id = null;
		try {
			id = entityClass.getDeclaredMethod(getGetter(idField)).invoke(t);
		} catch (Exception e) {
			logger.error("获取ID失败[" + entityClass.getName() + "#" + idField + "]：" + e.getMessage());
		}
		if (id != null && Integer.valueOf(0).equals(id)) {
			id = null;
		}

		if (null == id) {
			add(t);
		} else {
			update(t);
		}
	}

	@Override
	public int delete(final Integer id) {
		Table table = getTableAnnotation();
		String temp = table.idColumn();
		if (null == temp) {
			temp = translateField2Column(table.idField());
		}

		StringBuilder sql = new StringBuilder("DELETE FROM ").append(table.table()).append(" WHERE ").append(temp).append("=?");
		return jdbcTemplate.update(sql.toString(), new PreparedStatementSetter() {
			@Override
			public void setValues(PreparedStatement ps) throws SQLException {
				ps.setInt(1, id);
			}
		});
	}

	@Override
	public T load(Integer id) {
		Table table = getTableAnnotation();
		String temp = table.idColumn();
		if (null == temp) {
			temp = translateField2Column(table.idField());
		}

		StringBuilder sql = new StringBuilder("SELECT * FROM ").append(table.table()).append(" WHERE ").append(temp).append("=?");

		return jdbcTemplate.query(sql.toString(), new Object[]{id}, defaultEntityResultSetExtractor);
	}

	@Override
	public T get(String sql) {
		return jdbcTemplate.query(sql, defaultEntityResultSetExtractor);
	}

	@Override
	public T get(String sql, final Object... params) {
		return jdbcTemplate.query(sql, params, defaultEntityResultSetExtractor);
	}

	@Override
	public T get(String sql, Map<String, Object> alias) {
		return new NamedParameterJdbcTemplate(jdbcTemplate).query(sql, alias, defaultEntityResultSetExtractor);
	}

	@Override
	public int update(String sql) {
		return jdbcTemplate.update(sql);
	}

	@Override
	public int update(String sql, Object... params) {
		return jdbcTemplate.update(sql, params);
	}

	@Override
	public int update(String sql, Map<String, Object> alias) {
		return new NamedParameterJdbcTemplate(jdbcTemplate).update(sql, alias);
	}

	@Override
	public List<T> list(String sql) {
		return jdbcTemplate.query(sql, defaultListResultSetExtractor);
	}

	@Override
	public List<T> list(String sql, Object... params) {
		return jdbcTemplate.query(sql, params, defaultListResultSetExtractor);
	}

	@Override
	public List<T> list(String sql, Map<String, Object> alias) {
		return new NamedParameterJdbcTemplate(jdbcTemplate).query(sql, alias, defaultListResultSetExtractor);
	}

	@Override
	public Pagination<T> page(String sql, int page, int limit, Object... params) {
		if (page < 1) {
			page = 1;
		}
		if (limit < 1) {
			limit = 10;
		}

		Pagination<T> result = new Pagination<T>(page, limit);

		Object[] temp = null;
		if (params != null) {
			temp = new Object[params.length + 2];
			for (int i = 0; i < params.length; i++) {
				temp[i] = params[i];
			}
		} else {
			temp = new Object[2];
		}

		temp[temp.length - 2] = page * limit;
		temp[temp.length - 1] = (page - 1) * limit;

		result.setData(list("SELECT * FROM (SELECT A.*, ROWNUM " + ORACLE_ROWNUM_ALIAS + " FROM (" + sql + ") A WHERE ROWNUM<=?) WHERE " + ORACLE_ROWNUM_ALIAS + ">?", temp));

		return result;
	}

	@Override
	public Integer count() {
		return jdbcTemplate.query("SELECT COUNT(*) AS c FROM " + getTableAnnotation().table(), new ResultSetExtractor<Integer>() {
			@Override
			public Integer extractData(ResultSet rs) throws SQLException, DataAccessException {
				if (!rs.next()) {
					return Integer.valueOf(0);
				}

				return Integer.valueOf(rs.getInt("c"));
			}
		});
	}

	@Override
	public Integer count(String sql, Object... params) {
		return jdbcTemplate.query(sql, params, new ResultSetExtractor<Integer>() {
			@Override
			public Integer extractData(ResultSet rs) throws SQLException, DataAccessException {
				if (!rs.next()) {
					return Integer.valueOf(0);
				}

				return Integer.valueOf(rs.getInt(1));
			}
		});
	}

	@Override
	public Long sum(String sql, Object... params) {
		return jdbcTemplate.query(sql, params, new ResultSetExtractor<Long>() {
			@Override
			public Long extractData(ResultSet rs) throws SQLException, DataAccessException {
				if (!rs.next()) {
					return Long.valueOf(0);
				}

				return Long.valueOf(rs.getLong(1));
			}
		});
	}

	protected String getInsertSql() {
		Table table = getTableAnnotation();

		StringBuilder sql = new StringBuilder("INSERT INTO ");
		sql.append(table.table());
		sql.append(" (");

		int fieldCount = 0;
		Field[] fields = entityClass.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			String fieldName = field.getName();
			if ("createTime".equals(fieldName) || Modifier.isStatic(field.getModifiers())) {
				continue;
			}

			Persist persist = field.getAnnotation(Persist.class);
			if (null != persist) {
				String[] persistValues = persist.value();
				boolean uninsertable = false;
				for (int j = 0; j < persistValues.length; j++) {
					if (Persist.UNINSERTABLE.equals(persistValues[j])) {
						uninsertable = true;
						break;
					}
				}
				if (uninsertable) {
					continue;
				}
			}

			String temp = null;
			Column column = field.getAnnotation(Column.class);
			if (null != column && StringUtil.isNotBlank(column.value())) {
				temp = column.value();
			} else {
				temp = translateField2Column(fieldName);
			}

			sql.append(temp).append(",");
			fieldCount++;
		}

		if (fieldCount == 0) {
			throw new RuntimeException("没有要插入的数据");
		}

		sql.deleteCharAt(sql.length() - 1);
		sql.append(") VALUES (?");
		for (int i = 1; i < fieldCount; i++) {
			sql.append(",?");
		}
		sql.append(")");

		return sql.toString();
	}

	protected List<Object> getInsertParam(T t) {
		Table table = getTableAnnotation();
		String idField = table.idField();
		String sequence = table.sequence();
		if (StringUtils.isNotBlank(sequence)) {
			Integer id = jdbcTemplate.queryForObject("SELECT " + sequence + ".NEXTVAL FROM DUAL", Integer.class);
			try {
				entityClass.getDeclaredMethod(getSetter(idField), Integer.class).invoke(t, id);
			} catch (Exception e) {
				throw new RuntimeException("设置主键失败[" + entityClass.getName() + "#" + idField, e);
			}
		}

		final List<Object> values = new ArrayList<Object>();
		Field[] fields = entityClass.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			String fieldName = field.getName();
			if ("createTime".equals(fieldName) || Modifier.isStatic(field.getModifiers())) {
				continue;
			}

			Persist persist = field.getAnnotation(Persist.class);
			if (null != persist) {
				String[] persistValues = persist.value();
				boolean uninsertable = false;
				for (int j = 0; j < persistValues.length; j++) {
					if (Persist.UNINSERTABLE.equals(persistValues[j])) {
						uninsertable = true;
						break;
					}
				}
				if (uninsertable) {
					continue;
				}
			}

			Column column = field.getAnnotation(Column.class);
			try {
				Object value = entityClass.getDeclaredMethod(getGetter(fieldName)).invoke(t);
				if (column != null && value != null && column.isJson()) {
					value = SingletonObject.OBJECT_MAPPER.writeValueAsString(value);
				}
				values.add(value);
			} catch (Exception e) {
				logger.error("调用[" + entityClass.getName() + "#" + fieldName + "]的Getter方法异常");
			}
		}

		return values;
	}

	protected Table getTableAnnotation() {
		getEntityClass();

		Table table = entityClass.getAnnotation(Table.class);
		if (null == table) {
			throw new RuntimeException(entityClass.getName() + "不符合实体规范，请添加@Table注解!");
		}
		String tableName = table.table();
		if (null == tableName || "".equals(tableName.trim()) || tableName.indexOf(" ") != -1) {
			throw new RuntimeException(entityClass.getName() + "不符合实体规范，请检查@Table注解的table值:不能为空,不能包含空格");
		}
		String idField = table.idField();
		if (null == idField || "".equals(idField.trim()) || idField.indexOf(" ") != -1) {
			throw new RuntimeException(entityClass.getName() + "不符合实体规范，请检查@Table注解的id值:不能为空,不能包含空格");
		}

		return table;
	}

	protected T resolveOne(ResultSet rs) throws SQLException {
		if (!rs.next()) {
			return null;
		}

		T t = null;
		try {
			t = getEntityClass().newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		Table table = getTableAnnotation();
		String idField = table.idField();
		Field[] fields = entityClass.getDeclaredFields();
		Map<String, Field> columnFieldMap = new HashMap<>(fields.length);
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			if (Modifier.isStatic(field.getModifiers())) {
				continue;
			}

			String fieldName = field.getName();
			if (idField.equals(fieldName)) {
				String temp = table.idColumn();
				if (null == temp) {
					temp = translateField2Column(idField);
				}

				columnFieldMap.put(temp, field);
				continue;
			}

			String column = null;
			Column columnAnnotation = field.getAnnotation(Column.class);
			if (null == columnAnnotation) {
				column = translateField2Column(fieldName);
			} else {
				column = columnAnnotation.value();
			}

			columnFieldMap.put(column, field);
		}

		ResultSetMetaData metaData = rs.getMetaData();
		int columnCount = metaData.getColumnCount();
		for (int i = 1; i <= columnCount; i++) {
			Object value = rs.getObject(i);
			if (null == value) {
				continue;
			}

			String columnName = metaData.getColumnLabel(i).toLowerCase();
			if (ORACLE_ROWNUM_ALIAS.equals(columnName)) {
				continue;
			}

			Field field = columnFieldMap.get(columnName);
			if (null == field) {
				logger.error("Class[" + entityClass.getName() + "]中未发现数据库列[" + columnName + "]对应的字段!");
				continue;
			}

			String fieldName = field.getName();
			Class<?> fieldType = field.getType();
			Class<?> valueType = value.getClass();

			boolean isDatabaseEnum = false;
			Class<?>[] interfaces = fieldType.getInterfaces();
			for (int j = 0; j < interfaces.length; j++) {

			}
			Column column = field.getAnnotation(Column.class);
			if (isDatabaseEnum) {
				if (!fieldType.isEnum()) {
					logger.error("Field[" + fieldName + "]的类型为[" + fieldType + "]，该类型实现了middle.ground.dao.DatabaseEnum，但不是枚举!");
					continue;
				}

				Object[] enumConstants = fieldType.getEnumConstants();
			} else if (fieldType != valueType) {
				if (column != null && column.isJson()) {
					try {
						value = SingletonObject.OBJECT_MAPPER.readValue((String) value, field.getType());
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				} else {
					value = castValue(fieldType, valueType, value);
				}

			}

			try {
				entityClass.getDeclaredMethod(getSetter(fieldName), fieldType).invoke(t, value);
			} catch (Exception e) {
				logger.error("调用[" + entityClass.getName() + "#" + fieldName + "]的Setter方法异常：" + e.getMessage());
			}
		}

		return t;
	}

	protected List<T> resolve(ResultSet rs) throws SecurityException, SQLException {
		getEntityClass();

		Table table = getTableAnnotation();
		String idField = table.idField();
		Field[] fields = entityClass.getDeclaredFields();
		Map<String, Field> columnFieldMap = new HashMap<>(fields.length);
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			if (Modifier.isStatic(field.getModifiers())) {
				continue;
			}

			String fieldName = field.getName();
			if (idField.equals(fieldName)) {
				String temp = table.idColumn();
				if (null == temp) {
					temp = translateField2Column(idField);
				}

				columnFieldMap.put(temp, field);
				continue;
			}

			String column = null;
			Column columnAnnotation = field.getAnnotation(Column.class);
			if (null == columnAnnotation) {
				column = translateField2Column(fieldName);
			} else {
				column = columnAnnotation.value();
			}

			columnFieldMap.put(column, field);
		}

		List<T> result = new ArrayList<T>();
		while (rs.next()) {
			T t = null;
			try {
				t = entityClass.newInstance();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}

			ResultSetMetaData metaData = rs.getMetaData();
			int columnCount = metaData.getColumnCount();
			for (int i = 1; i <= columnCount; i++) {
				Object value = rs.getObject(i);
				if (null == value) {
					continue;
				}

				String columnName = metaData.getColumnLabel(i).toLowerCase();
				if (ORACLE_ROWNUM_ALIAS.equals(columnName)) {
					continue;
				}

				Field field = columnFieldMap.get(columnName);
				if (null == field) {
					logger.error("Class[" + entityClass.getName() + "]中未发现数据库列[" + columnName + "]对应的字段!");
					continue;
				}

				String fieldName = field.getName();
				Class<?> fieldType = field.getType();
				Class<?> valueType = value.getClass();

				boolean isDatabaseEnum = false;
				Class<?>[] interfaces = fieldType.getInterfaces();

				Column column = field.getAnnotation(Column.class);
				if (isDatabaseEnum) {
					if (!fieldType.isEnum()) {
						logger.error("Field[" + fieldName + "]的类型为[" + fieldType + "]，该类型实现了middle.ground.dao.DatabaseEnum，但不是枚举!");
						continue;
					}

					Object[] enumConstants = fieldType.getEnumConstants();
				} else if (fieldType != valueType) {
					if (column != null && column.isJson()) {
						try {
							value = SingletonObject.OBJECT_MAPPER.readValue((String) value, field.getType());
						} catch (Exception e) {
							throw new RuntimeException(e);
						}
					} else {
						value = castValue(fieldType, valueType, value);
					}
				}

				try {
					entityClass.getDeclaredMethod(getSetter(fieldName), fieldType).invoke(t, value);
				} catch (Exception e) {
					logger.error("调用[" + entityClass.getName() + "#" + fieldName + "]的Setter方法异常：" + e.getMessage());
				}
			}

			result.add(t);
		}

		return result;
	}

	@SuppressWarnings("deprecation")
	protected Object castValue(Class<?> fieldType, Class<?> valueType, Object value) {
		if (fieldType == Integer.class) {
			if (Long.class == valueType) {
				value = ((Long) value).intValue();
			} else if (Float.class == valueType) {
				value = ((Float) value).intValue();
			} else if (Double.class == valueType) {
				value = ((Double) value).intValue();
			} else if (BigDecimal.class == valueType) {
				value = ((BigDecimal) value).intValue();
			} else if (Timestamp.class == valueType) {
				value = (int) (((Date) value).getTime());
			} else if (String.class == valueType) {
				value = Integer.valueOf((String) value);
			} else if (Boolean.class == valueType) {
				value = ((Boolean) value) ? 1 : 0;
			} else if (BigInteger.class == valueType) {
				value = ((BigInteger) value).intValue();
			}
		} else if (fieldType == Long.class) {
			if (Integer.class == valueType) {
				value = ((Integer) value).longValue();
			} else if (Float.class == valueType) {
				value = ((Float) value).longValue();
			} else if (Double.class == valueType) {
				value = ((Double) value).longValue();
			} else if (BigDecimal.class == valueType) {
				value = ((BigDecimal) value).longValue();
			} else if (Timestamp.class == valueType) {
				value = ((Date) value).getTime();
			} else if (String.class == valueType) {
				value = Long.valueOf((String) value);
			} else if (Boolean.class == valueType) {
				value = ((Boolean) value) ? 1 : 0;
			} else if (BigInteger.class == valueType) {
				value = ((BigInteger) value).longValue();
			}
		} else if (fieldType == Float.class) {
			if (Integer.class == valueType) {
				value = ((Integer) value).floatValue();
			} else if (Long.class == valueType) {
				value = ((Long) value).floatValue();
			} else if (Double.class == valueType) {
				value = ((Double) value).floatValue();
			} else if (BigDecimal.class == valueType) {
				value = ((BigDecimal) value).floatValue();
			} else if (Timestamp.class == valueType) {
				value = ((Date) value).getTime();
			} else if (String.class == valueType) {
				value = Float.valueOf((String) value);
			} else if (Boolean.class == valueType) {
				value = ((Boolean) value) ? 1 : 0;
			} else if (BigInteger.class == valueType) {
				value = ((BigInteger) value).floatValue();
			}
		} else if (fieldType == Double.class) {
			if (Float.class == valueType) {
				value = ((Float) value).doubleValue();
			} else if (BigDecimal.class == valueType) {
				value = ((BigDecimal) value).doubleValue();
			} else if (Integer.class == valueType) {
				value = ((Integer) value).doubleValue();
			} else if (Long.class == valueType) {
				value = ((Long) value).doubleValue();
			} else if (Timestamp.class == valueType) {
				value = ((Date) value).getTime();
			} else if (String.class == valueType) {
				value = Double.valueOf((String) value);
			} else if (Boolean.class == valueType) {
				value = ((Boolean) value) ? 1 : 0;
			} else if (BigInteger.class == valueType) {
				value = ((BigInteger) value).doubleValue();
			}
		} else if (fieldType == BigDecimal.class) {
			if (Integer.class == valueType) {
				value = BigDecimal.valueOf((Integer) value);
			} else if (Long.class == valueType) {
				value = BigDecimal.valueOf((Long) value);
			} else if (Float.class == valueType) {
				value = BigDecimal.valueOf((Float) value);
			} else if (Double.class == valueType) {
				value = BigDecimal.valueOf((Double) value);
			} else if (Timestamp.class == valueType) {
				value = BigDecimal.valueOf(((Date) value).getTime());
			} else if (String.class == valueType) {
				value = BigDecimal.valueOf(Double.valueOf((String) value));
			} else if (Boolean.class == valueType) {
				value = BigDecimal.valueOf(((Boolean) value) ? 1 : 0);
			} else if (BigInteger.class == valueType) {
				value = BigDecimal.valueOf(((BigInteger) value).doubleValue());
			}
		} else if (fieldType == BigInteger.class) {
			if (Integer.class == valueType) {
				value = BigInteger.valueOf((Integer) value);
			} else if (Long.class == valueType) {
				value = BigInteger.valueOf((Long) value);
			} else if (Float.class == valueType) {
				value = BigInteger.valueOf(((Float) value).intValue());
			} else if (Double.class == valueType) {
				value = BigInteger.valueOf(((Double) value).longValue());
			} else if (Timestamp.class == valueType) {
				value = BigInteger.valueOf(((Date) value).getTime());
			} else if (String.class == valueType) {
				value = BigInteger.valueOf(Double.valueOf((String) value).longValue());
			} else if (Boolean.class == valueType) {
				value = BigInteger.valueOf(((Boolean) value) ? 1 : 0);
			} else if (BigDecimal.class == valueType) {
				value = BigInteger.valueOf(((BigDecimal) value).longValue());
			}
		} else if (fieldType == Date.class) {
			if (Integer.class == valueType) {
				value = new Date((Integer) value);
			} else if (Long.class == valueType) {
				value = new Date((Long) value);
			} else if (Float.class == valueType) {
				value = new Date(((Float) value).longValue());
			} else if (Double.class == valueType) {
				value = new Date(((Double) value).longValue());
			} else if (String.class == valueType) {
				value = new Date((String) value);
			} else if (Boolean.class == valueType) {
				//布尔true代表当前时间，false代表null
				value = ((Boolean) value) ? new Date() : null;
			} else if (BigDecimal.class == valueType) {
				value = new Date(((BigDecimal) value).longValue());
			}
		} else if (fieldType == String.class) {
			value = value.toString();
		}

		return value;
	}

	private static String getGetter(String fieldName) {
		return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
	}

	private static String getSetter(String fieldName) {
		return "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
	}

	/**
	 * 将实体字段转换成表字段
	 *
	 * @param name
	 * @return
	 */
	private static String translateField2Column(String name) {
		StringBuilder result = new StringBuilder();
		char[] chars = name.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			char c = chars[i];
			if (i == 0) {
				if (c >= 'A' && c <= 'Z') {
					result.append((char) (chars[i] + 32));
				} else {
					result.append(c);
				}
			} else {
				if (c >= 'A' && c <= 'Z') {
					result.append("_").append((char) (chars[i] + 32));
				} else {
					result.append(c);
				}
			}
		}

		return result.toString();
	}
}
